<?php

namespace App\Kuafu\Shop\Service;

use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Shop\Enum\CameraCacheEnum;
use App\Kuafu\Shop\Enum\CodeEnum;
use App\Kuafu\Shop\Model\CameraModel;
use App\Kuafu\Shop\Model\GuanyuanSyncShopListModel;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\Shop\Model\ShopArchives;
use App\Kuafu\Shop\Service\CameraLibrary\CameraFactory;
use App\Kuafu\User\Model\User;
use App\Kuafu\User\Service\UserService;
use App\Remote\Tiger\OpenShop\OpenShopRemote;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;


class DeviceCameraService extends BaseService
{

    public function getCameraListByShopId(int $isNew = 0): array
    {
        if (!$isNew) {
            return CameraService::getCameraList($this->shopId)->toArray();
        }
        $info                       = ShopService::getShopInfo($this->shopId);// 门店信息
        $shopBusinessTimeChangeByDb = ShopService::getShopBusinessTimeChangeByDb($info['startAt'], $info['endAt']);

        $shopArchives = ShopArchives::query()->where('shopId', $this->shopId)->first();// 门店附加信息
        $cameraStatus = $shopArchives->cameraStatus ?? 0;

        // 观远门店状态数据
        $shopBusiness   = GuanyuanSyncShopListModel::query()
                                                   ->where('code', $info['shopCode'])
                                                   ->select('status')
                                                   ->first();
        $guanyuanStatus = $shopBusiness->status ?? '';


        // 查询门店督导/稽核
        $userList     = User::query()
                            ->whereIn('id', [$info['councilorId']])
                            ->select(['id', 'username'])
                            ->get()
                            ->keyBy('id')
                            ->toArray();

        // 根据门店区域查询稽核人员id
        $getShopCruiseManage = OpenShopRemote::getShopCruiseManageArea([],
                $info['province'] . '-' . $info['city'] . '-' . $info['district']) ?? [];

        $getShopCruiseManageId   = $getShopCruiseManage[0]['userId'] ?? 0;
        $getShopCruiseManageName = $getShopCruiseManage[0]['name'] ?? '';

        $shopInfo = [
            'id'               => $info['id'],
            'shopCode'         => $info['shopCode'],
            'name'             => $info['name'],
            'address'          => $info['address'],
            'addressPrefix'    => $info['addressPrefix'],
            'startAt'          => $shopBusinessTimeChangeByDb['startAt'],
            'endAt'            => $shopBusinessTimeChangeByDb['endAt'],
            'councilorId'      => $info['councilorId'] ?? 0,
            'councilorName'    => $userList[$info['councilorId'] ?? 0]['username'] ?? '',// 督导
            'cruiseManageId'   => $getShopCruiseManageId,// 稽核人员id
            'cruiseManageName' => $getShopCruiseManageName,
            'cameraStatus'     => $cameraStatus,// 摄像头状态
            'cameraStatusText' => CodeEnum::SHOP_CAMERA_STATUS_TYPE_TEXT[$cameraStatus] ?? '',// 摄像头状态
            'guanyuanStatus'   => $guanyuanStatus,// 观远门店状态
        ];

        $cameraList = CameraService::getCameraList($this->shopId, 0)->toArray();
        self::updateCameraStatus($cameraList, $this->shopId, $cameraStatus);// 更新摄像头状态
        return [
            'shopInfo'   => $shopInfo,
            'cameraList' => $cameraList,
        ];
    }

    /**
     * @throws Exception
     */
    public function getCameraIdById(
        int $id,
        ?string $scheme = 'hls',
        int $clarity = CodeEnum::CLARITY_TYPE_FLUENCY
    ): array {
        $camera = new CameraFactory($id);

        $streamData = $camera->getIns()->getLiveStreaming($scheme, $clarity);

        return [
            'id'        => $camera->cameraInfo->id,
            'name'      => $camera->cameraInfo->name,
            'streamUrl' => $streamData['url'] ?? ''
        ];
    }

    /**
     * 指定录像时间范围的录像文件播放时间段。
     *
     * @param int $id
     * @param int $timestamp
     * @return array
     * @throws Exception
     */
    public function queryDeviceVodUrlByTimeByInvoke(int $id, int $timestamp): array
    {
        $camera = new CameraFactory($id);
        return [
            'id'       => $camera->cameraInfo->id,
            'name'     => $camera->cameraInfo->name,
            'timeList' => $camera->getIns()->localVideoList($timestamp, $timestamp + 86400)
        ];
    }

    /**
     * 指定录像时间范围的录像文件播放地址。
     *
     * @param int $id
     * @param string $scheme
     * @param string $startAtDate
     * @param int $seekTime
     * @return array
     * @throws Exception
     */
    public function queryDeviceVodUrlByTime(int $id, string $scheme, string $startAtDate, int $seekTime = 0): array
    {
        $startAt    = strtotime($startAtDate);
        $endAt      = $startAt + 86400;
        $camera     = new CameraFactory($id);
        $streamData = $camera->getIns()->backUrl($startAt, $endAt, $seekTime, $scheme);

        return [
            'id'        => $camera->cameraInfo->id,
            'name'      => $camera->cameraInfo->name,
            'streamUrl' => $streamData['url']
        ];
    }

    /**
     * 摄像头设备列表-门店搜索
     * @param array $search
     * @param int $pageNum
     * @param int $pageSize
     * @return array
     */
    public static function getCameraListByShopIds(array $search, int $pageNum, int $pageSize): array
    {
        $shopIds = $searchShopIdCodes = $statusTexts = [];

        if ($search['guanyuanStatus']) { // 观远门店状态 1-正常营业 2-暂停营业 3-筹备中 4-选址中
            foreach ($search['guanyuanStatus'] as $v) {
                $statusText = CodeEnum::SHOP_GUANYUAN_STATUS_TYPE_TEXT[$v] ?? '';
                if (!$statusText) {
                    continue;
                }
                $statusTexts[] = $statusText;
            }
        }

        $councilorUserIds = [];
        if ($search['councilorName']) { // 督导名称
            $councilorUserIds = UserService::getRmsUserIdByUserName($search['councilorName']);
            if (!$councilorUserIds) {
                $councilorUserIds = ['-1'];
            }
        }

        $provinceCodes = $cityCodes = $regionCodes = [];
        if ($search['cruiseName']) { // 稽核名称
            $cruiseUserIds = array_column(UserService::getRmsUserIdByUserName($search['cruiseName']) ?? [], 'id');
            if ($cruiseUserIds) {
                $getShopCruiseManageArea = OpenShopRemote::getShopCruiseManageArea($cruiseUserIds) ?? [];// 根据稽核人员id查询对应门店区域
                if ($getShopCruiseManageArea) {
                    foreach ($getShopCruiseManageArea as $v) {
//                        $provinceCodes = array_merge($provinceCodes, array_column($v['addressCodesArr'], 'provinceCode'));
//                        $cityCodes     = array_merge($cityCodes, array_column($v['addressCodesArr'], 'cityCode'));
                        $regionCodes   = array_merge($regionCodes, array_column($v['addressCodesArr'], 'regionCode'));

                    }
//                    $provinceCodes = array_unique($provinceCodes);
//                    $cityCodes     = array_unique($cityCodes);
                    $regionCodes   = array_unique($regionCodes);// 按照区查询
                } else {
                    $regionCodes = ['-1'];
                }
            } else {
                $regionCodes = ['-1'];
            }
        }

        $notShopIds = [];
        if ($search['startTime'] && $search['endTime']) { // 未巡检日期

            // 根据巡检日期查询门店id
            $notShopIds = OpenShopRemote::getShopIdsByTourCruise($search['startTime'], $search['endTime']) ?? [];
        }

        // 摄像头数据总计
        $shopCameraCount = Shop::query()
                               ->join('shop_archives', 'shop_archives.shopId', '=', 'shops.id')
                               ->when($statusTexts, function ($query) { // 观远门店状态搜索
                                   $query->leftJoin('guanyuan_sync_shop_list', 'guanyuan_sync_shop_list.code', '=',
                                       'shops.shopCode');
                               })
                               ->when($search['shopIds'], function ($query) use ($search) {// 搜索门店id
                                   $query->whereIn('shops.id', $search['shopIds']);
                               })
                               ->when($search['name'], function ($query) use ($search) { // 门店编号/名称
                                   if (is_numeric($search['name'])) {
                                       $query->where('shops.shopCode', $search['name']);
                                   } else {
                                       $query->where('shops.name', 'like', "%{$search['name']}%");
                                   }
                               })
                               ->where(function ($query) use (
                                   $statusTexts,
                                   $notShopIds,
                                   $regionCodes,
                                   $councilorUserIds,
                                   $shopIds,
                                   $search
                               ) {
                                   $query->whereIn('shops.status',
                                       [CodeEnum::SHOP_STATUS_NORMAL, CodeEnum::SHOP_STATUS_PREPARE])
                                         ->when($shopIds, function ($query) use ($shopIds) {
                                             $query->whereIn('shops.id', $shopIds);
                                         })->when($councilorUserIds, function ($query) use ($councilorUserIds) { // 督导搜索
                                           $query->whereIn('shops.councilorId', $councilorUserIds);
                                       })->when($regionCodes, function ($query) use ($regionCodes) { // 稽核搜索
                                           $query->whereIn('shops.district', $regionCodes);
                                       })->when($search['cameraStatus'], function ($query) use ($search) { // 摄像头状态
                                           $query->whereIn('shop_archives.cameraStatus', $search['cameraStatus']);
                                       })->when($notShopIds, function ($query) use ($notShopIds) { // 未巡检日期匹配门店
                                           $query->whereNotIn('shops.id', $notShopIds);
                                       })->when($statusTexts, function ($query) use ($statusTexts) { // 观远门店状态搜索
                                           $query->whereIn('guanyuan_sync_shop_list.status', $statusTexts);
                                       });
                               })
                               ->selectRaw('kf_shop_archives.cameraStatus,count(1) num')
                               ->groupBy('shop_archives.cameraStatus')
                               ->get()
                               ->keyBy('cameraStatus')
                               ->toArray();

        $total = [
            'totalCount'         => array_sum(array_column($shopCameraCount, 'num')),
            'totalOnline'        => $shopCameraCount[CodeEnum::SHOP_CAMERA_STATUS_ONLINE]['num'] ?? 0,// 在线
            'totalOffOnline'     => $shopCameraCount[CodeEnum::SHOP_CAMERA_STATUS_OFF_ONLINE]['num'] ?? 0,// 离线
            'totalNotFound'      => $shopCameraCount[CodeEnum::SHOP_CAMERA_STATUS_NOT_FOUND]['num'] ?? 0,// 缺失
            'totalPartialOnline' => $shopCameraCount[CodeEnum::SHOP_CAMERA_STATUS_PARTIAL_ONLINE]['num'] ?? 0,// 部分在线
        ];

        // 门店摄像头数据列表
        $paginator = Shop::query()
                         ->join('shop_archives', 'shop_archives.shopId', '=', 'shops.id')
                         ->when($statusTexts, function ($query) { // 观远门店状态搜索
                             $query->leftJoin('guanyuan_sync_shop_list', 'guanyuan_sync_shop_list.code', '=',
                                 'shops.shopCode');
                         })
                         ->when($search['shopIds'], function ($query) use ($search) {// 搜索门店id
                             $query->whereIn('shops.id', $search['shopIds']);
                         })
                         ->when($search['name'], function ($query) use ($search) { // 门店编号/名称
                             if (is_numeric($search['name'])) {
                                 $query->where('shops.shopCode', $search['name']);
                             } else {
                                 $query->where('shops.name', 'like', "%{$search['name']}%");
                             }
                         })
                         ->where(function ($query) use (
                             $statusTexts,
                             $notShopIds,
                             $regionCodes,
                             $councilorUserIds,
                             $shopIds,
                             $search
                         ) {
                             $query->whereIn('shops.status',
                                 [CodeEnum::SHOP_STATUS_NORMAL, CodeEnum::SHOP_STATUS_PREPARE])
                                   ->when($shopIds, function ($query) use ($shopIds) {
                                       $query->whereIn('shops.id', $shopIds);
                                   })->when($councilorUserIds, function ($query) use ($councilorUserIds) { // 督导搜索
                                     $query->whereIn('shops.councilorId', $councilorUserIds);
                                 })->when($regionCodes, function ($query) use ($regionCodes) { // 稽核搜索
                                     $query->whereIn('shops.district', $regionCodes);
                                 })->when($search['cameraStatus'], function ($query) use ($search) { // 摄像头状态
                                     $query->whereIn('shop_archives.cameraStatus', $search['cameraStatus']);
                                 })->when($notShopIds, function ($query) use ($notShopIds) { // 未巡检日期匹配门店
                                     $query->whereNotIn('shops.id', $notShopIds);
                                 })->when($statusTexts, function ($query) use ($statusTexts) { // 观远门店状态搜索
                                     $query->whereIn('guanyuan_sync_shop_list.status', $statusTexts);
                                 });
                         })
                         ->orderBy('shops.id')
                         ->paginate($pageSize,
                             ['shops.id', 'shops.name', 'shops.shopCode', 'shop_archives.cameraStatus'],
                             'page', $pageNum);

        return [
            'list'     => $paginator->map(function ($item) {
                return [
                    'id'               => $item->id,
                    'name'             => $item->name,
                    'shopCode'         => $item->shopCode,
                    'cameraStatus'     => $item->cameraStatus ?? 0,
                    'cameraStatusText' => CodeEnum::SHOP_CAMERA_STATUS_TYPE_TEXT[$item->cameraStatus ?? 0] ?? '',
                ];
            }),
            'pageNum'  => $paginator->currentPage(),
            'pageSize' => $paginator->perPage(),
            'count'    => $paginator->total(),
            'total'    => $total,
        ];
    }

    /**
     * 更新摄像头状态
     * @param array $cameraList
     * @param int $shopId
     * @param int $cameraOldStatus
     * @throws Exception
     */
    public static function updateCameraStatus(array $cameraList, int $shopId, int $cameraOldStatus)
    {
        $total            = count($cameraList);
        $shopCameraStatus = CodeEnum::SHOP_CAMERA_STATUS_NOT_FOUND;// 门店摄像头默认状态-缺失
        $updateRes        = 0;// 更新数据库记录是否成功
        try {
            if ($total > 0) {

                // 批量获取摄像头状态
                $first            = $cameraList[0];
                $camera           = new CameraFactory($first['id']);
                $cameraStatusList = $camera->getIns()->getDeviceStatusBatch($cameraList);
                $cameraStatusList = array_column($cameraStatusList, null, 'id');

                $onlineCount    = 0;// 在线数量
                $offOnlineCount = 0;// 离线数量
                foreach ($cameraList as $item) {
                    $oldStatus    = $item['status'];
                    $newStatus    = $cameraStatusList[$item['id']]['status'] ?? 0;
                    $cameraStatus = $newStatus == 1 ? CodeEnum::SHOP_CAMERA_STATUS_ONLINE : CodeEnum::SHOP_CAMERA_STATUS_OFF_ONLINE;// 摄像头状态 0-缺失 1-在线 2-离线 3-部分在线

                    if ($cameraStatus == CodeEnum::SHOP_CAMERA_STATUS_ONLINE) {
                        $onlineCount++;
                    } elseif ($cameraStatus == CodeEnum::SHOP_CAMERA_STATUS_OFF_ONLINE) {
                        $offOnlineCount++;
                    }

                    // 修改单个摄像头状态
                    if ($oldStatus != $cameraStatus) {
                        $res = CameraModel::query()
                                          ->where('id', $item['id'])
                                          ->update(['status' => $cameraStatus]);
                        if ($res) {
                            $updateRes = 1;
                        }
                    }
                }

                if ($onlineCount == $total) {
                    $shopCameraStatus = CodeEnum::SHOP_CAMERA_STATUS_ONLINE;// 全部在线
                } elseif ($offOnlineCount == $total) {
                    $shopCameraStatus = CodeEnum::SHOP_CAMERA_STATUS_OFF_ONLINE;// 全部离线
                } else {
                    $shopCameraStatus = CodeEnum::SHOP_CAMERA_STATUS_PARTIAL_ONLINE;// 部分在线
                }

            }

            // 修改门店摄像头状态
            if ($cameraOldStatus != $shopCameraStatus) {
                ShopArchives::query()
                            ->where('shopId', $shopId)
                            ->update(['cameraStatus' => $shopCameraStatus]);
            }
        } catch (Exception $e) {
            Log::warning('updateCameraStatusErr', [
                'cameraList'      => $cameraList,
                'shopId'          => $shopId,
                'cameraOldStatus' => $cameraOldStatus,
                'msg'             => $e->getMessage(),
            ]);
        }
        if ($updateRes) {
            Cache::forget(CameraCacheEnum::getCameraListCacheKey($shopId));
        }
    }
}
